#include "band.h"
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

bool band::init()
{
    if(!kp.input()) return false;
    cartesian();
    distance.resize(kp.k_num());
    distance[0]=0;
    for(uint i=1;i<kp.k_num();i++){
        distance[i]=(kp[i]-kp[i-1]).norm();
    }
    FindHSPSymbol();
    kp.set_Efermi();
    return true;
}

void band::FindHSPSymbol()
{
    const char * ptr;
    ptr=RLV.HighSymPnt(kp[0]);
    symbol.push_back(ptr);
    symbolDis.push_back(0);
    data L=0;
    for(uint i=1;i<kp.k_num()-1;i++){
        if(distance[i]<RLV.ERROR) continue;
        L+=distance[i];
        ptr=RLV.HighSymPnt(kp[i]);
        if(ptr){
            symbol.push_back(ptr);
            symbolDis.push_back(L);
        }
    }
    L+=distance.back();
    ptr=RLV.HighSymPnt(kp[kp.k_num()-1]);
    symbol.push_back(ptr);
    symbolDis.push_back(L);
    //for(int i=0;i<symbol.size();i++){
    //    printf("%f %s\n",symbolDis[i],symbol[i]);
    //}
}

void band::GetLettVector()
{
    FILE *ipf=fopen("POSCAR","r");
    if(!ipf){
        perror("POSCAR");
        exit(0);
    }
    char s[100];
    data scale;
    fgets(s,100,ipf);
    fgets(s,100,ipf);
    sscanf(s, "%f",&scale);
    for(int i=0;i<3;i++){
        fgets(s,100,ipf);
        sscanf(s, "%f%f%f",&RLV[i][0],&RLV[i][1],&RLV[i][2]);
    }
    fclose(ipf);
    RLV*=scale;
    RLV.FindHSP();
    RLV.HSPSymbol();
}

void band::cartesian()
{
    if(called) return;
    if(RLV[0].norm()<RLV.ERROR) GetLettVector();
    RLV=RLV.GetRLV();
    //for(int i=0;i<3;i++){
    //    RLV[i].show();
    //    std::cout<<std::endl;
    //}
    for(uint i=0;i<kp.k_num();i++) kp[i]*=RLV;
    called=true;
}

void band::SetFermiEnergy(data energy)
{
    kp.Efermi=energy;
}
void band::output()
{
    switch(kp.s_num()){
        case 1:
            BandSpin1();
            break;
        case 2:
            BandSpin2();
            break;
    }
}

void band::BandSpin1()
{
    FILE *opf=fopen("bandstructure.txt","w");
    fprintf(opf,"%12s","KPATH");
    for(uint i=0;i<kp.b_num();i++) {
        char s[16];
        sprintf(s,"band:%d",i);
        fprintf(opf,"%12s",s);
    }
    fprintf(opf,"%12s\n","HSP");
    data L=0;
    for(uint i =0;i<symbol.size();i++){
        L+=distance[i];
        fprintf(opf,"%12f",L);
        for(uint j = 0;j<kp.b_num();j++){
            fprintf(opf," %11f",kp(i,j,0));
        }
        fprintf(opf,"%12f %s\n",symbolDis[i],symbol[i]);
    }
    for(uint i=symbol.size();i<kp.k_num();i++){
        L+=distance[i];
        fprintf(opf,"%12f",L);
        for(uint j = 0;j<kp.b_num();j++){
            fprintf(opf," %11f",kp(i,j,0));
        }
        fprintf(opf,"\n");
    }
    fclose(opf);
}

void band::BandSpin2()
{
    FILE *up=fopen("bandup.txt","w");
    FILE *dw=fopen("banddown.txt","w");
    fprintf(up,"%12s","KPATH");
    fprintf(dw,"%12s","KPATH");
    for(uint i=0;i<kp.b_num();i++) {
        char s[16];
        sprintf(s,"band:%d",i);
        fprintf(up,"%12s",s);
        fprintf(dw,"%12s",s);
    }
    fprintf(up,"%12s\n","HSP");
    fprintf(dw,"%12s\n","HSP"); 
    data L=0;
    for(uint i =0;i<symbol.size();i++){
        L+=distance[i];
        fprintf(up,"%12f",L);
        fprintf(dw,"%12f",L);
        for(uint j = 0;j<kp.b_num();j++){
            fprintf(up," %11f",kp(i,j,0));
            fprintf(dw," %11f",kp(i,j,1));
        }
        fprintf(up,"%12f %s\n",symbolDis[i],symbol[i]);
        fprintf(dw,"%12f %s\n",symbolDis[i],symbol[i]);
    }
    for(uint i=symbol.size();i<kp.k_num();i++){
        L+=distance[i];
        fprintf(up,"%12f",L);
        fprintf(dw,"%12f",L);
        for(uint j = 0;j<kp.b_num();j++){
            fprintf(up," %11f",kp(i,j,0));
            fprintf(dw," %11f",kp(i,j,1));
        }
        fprintf(up,"\n");
        fprintf(dw,"\n");
    }
    fclose(up);
    fclose(dw);
}

void band::Gnuplot()
{
    if(!gnuplot) return;
    switch(kp.s_num()){
        case 1:
            GnuSpin1();
            break;
        case 2:
            GnuSpin2();
            break;
    }
}

void band::GnuSpin1()
{
    FILE *opf=fopen("bandplot.plt","w");
    fprintf(opf,"#格式，大小和字体\nset terminal pdfcairo enhanced size 7.5,5.3 font 'Arial,36'\n");
    fprintf(opf,"#输出的文件名\nset output 'band.pdf'\n");
    fprintf(opf,"set border lw 2\n");
    fprintf(opf,"set ylabel '{/Arial:Italic E-E_{f}} (eV)'\n");
    fprintf(opf,"bu='bandstructure.txt'\n");

    /*print label*/
    fprintf(opf,"set xrange [0: %f]\n",symbolDis.back());
    fprintf(opf,"set xtics ('%s' %f",symbol[0],symbolDis[0]);
    for(uint i=1;i<symbol.size();i++){
        fprintf(opf,", '%s' %f",symbol[i],symbolDis[i]);
    }    
    fprintf(opf,")\n");

    
    fprintf(opf,"set yrange [%g: %g]\n",range[0],range[1]);
    fprintf(opf,"set ytics %g,%g,%g\n",range[0],increase,range[1]);
    fprintf(opf,"set mytics 2\n");
    fprintf(opf,"set xtics nomirror\n");
    fprintf(opf,"set ytics nomirror\n");
    fprintf(opf,"unset x2tics\n");
    fprintf(opf,"unset y2tics\n");
    fprintf(opf,"unset title\n");
    fprintf(opf,"set xzeroaxis dashtype 4 linewidth 2 \n");
    fprintf(opf,"set grid xtics dashtype 1 linewidth 2 \n");
    fprintf(opf,"plot for [i=2:%d] bu u 1:i w l linewidth 4 linecolor 'black' notitle\n",kp.b_num()+1);
}

void band::GnuSpin2()
{
    FILE *opf=fopen("bandplot.plt","w");
    fprintf(opf,"#格式，大小和字体\nset terminal pdfcairo enhanced size %.1f,5.3 font 'Arial,36'\n",plots*7.5);
    fprintf(opf,"#输出的文件名\nset output 'band.pdf'\n");
    if(plots==2)fprintf(opf,"set multiplot layout 1,2 \n");
    fprintf(opf,"set border lw 2\n");
    fprintf(opf,"set ylabel '{/Arial:Italic E-E_{f}} (eV)'\n");
    fprintf(opf,"bu='bandup.txt'\n");
    fprintf(opf,"bd='banddown.txt'\n");

    /*print label*/
    fprintf(opf,"set xrange [0: %f]\n",symbolDis.back());
    fprintf(opf,"set xtics ('%s' %f",symbol[0],symbolDis[0]);
    for(uint i=1;i<symbol.size();i++){
        fprintf(opf,", '%s' %f",symbol[i],symbolDis[i]);
    }    
    fprintf(opf,")\n");

    
    fprintf(opf,"set yrange [%g: %g]\n",range[0],range[1]);
    fprintf(opf,"set ytics %g,%g,%g\n",range[0],increase,range[1]);
    fprintf(opf,"set mytics 2\n");
    fprintf(opf,"set xtics nomirror\n");
    fprintf(opf,"set ytics nomirror\n");
    fprintf(opf,"unset x2tics\n");
    fprintf(opf,"unset y2tics\n");
    fprintf(opf,"unset title\n");
    fprintf(opf,"set xzeroaxis dashtype 4 linewidth 2 \n");
    fprintf(opf,"set grid xtics dashtype 1 linewidth 2 \n");    
    if(plots==2){
        fprintf(opf,"plot for [i=2:%d] bu u 1:i w l linewidth 4 linecolor 'red' notitle\n",kp.b_num()+1);
        fprintf(opf,"plot for [i=2:%d] bd u 1:i w l linewidth 4 linecolor 'blue' notitle\n",kp.b_num()+1);
    }
    else{        
        fprintf(opf,"plot for [i=2:%d] bu u 1:i w l linewidth 4 linecolor 'red'  notitle, \\\n",kp.b_num()+1);
        fprintf(opf,"     for [i=2:%d] bd u 1:i w l linewidth 4 linecolor 'blue' notitle\n",kp.b_num()+1);
    }
}

void band::ShowHSP()
{
    if(RLV[0].norm()<RLV.ERROR) GetLettVector();
    RLV.ShowHSP();
}

void band::FindFermiEnergy()
{
    FILE *ipf;
    char s[80];
    #ifdef _WIN32
    int (*Access)(const char *,int)=_access;
    const int exist=0;
    #else
    int (*Access)(const char *,int)=access;
    const int exist=4;
    #endif
    if(!Access("DOSCAR",exist)){
        ipf=fopen("DOSCAR","r");
        for(int i=0;i<6;i++){
            fgets(s,80,ipf);
        }
        sscanf(s,"%*f%*f%*u%f",&kp.Efermi);
        fclose(ipf);
    }else if(!Access("OUTCAR",exist)){
        ipf=fopen("OUTCAR","r");
        while(fgets(s,80,ipf)){
            if(s[0]==' '&& s[1]=='E' && s[2]=='-'){
                sscanf(s,"%*s%*s%f",&kp.Efermi);
                break;
            }
        }
        fclose(ipf);
    }else{
        perror("DOSCAR");
        perror("OUTCAR");
    }
}